/**
 * reduce() 方法对数组中的每个元素按序执行一个提供的 reducer 函数，每一次运行 reducer 会将先前元素的计算结果作为参数传入，
 * 最后将其结果汇总为单个返回值。

第一次执行回调函数时，不存在“上一次的计算结果”。如果需要回调函数从数组索引为 0 的元素开始执行，则需要传递初始值。
否则，数组索引为 0 的元素将被用作初始值，迭代器将从第二个元素开始执行（即从索引为 1 而不是 0 的位置开始）。

注：不传入初始值，默认初始值是数组第一个值，并且从第二个元素开始遍历
    传入初始值，从第一个元素开始遍历
 * @param {*} callback 
 * @param {*} initVal 
 */
Array.prototype.myReduce = function (callback, initVal) {
  if (typeof callback != "function") {
    throw new TypeError("callback is a function o~");
  }

  // 数组不能为空
  if (!this.length) {
    throw new Error("Reduce of empty array with no initial value");
  }

  let cacleRes = initVal ?? this[0]; // 取初始值
  const startIndex = Number(initVal === undefined); // 开始元素
  const len = this.length;

  for (let i = startIndex; i < len; i++) {
    cacleRes = callback(cacleRes, this[i], i, this);
  }
  return cacleRes;
};

// egg
let arr = [1, 2, 3, 4, 5];
const res = arr.myReduce((a, b, i) => {
  console.log("[ i ] >", i);
  return a + b;
});
console.log("[ res ] >", res);

const res2 = arr.reduce((a, b, i) => {
  console.log("[ i ] >", i);
  return a + b;
});
console.log("[ ress2 ] >", res2);
